package antlr.caculator.app;

import antlr.caculator.gramma.caculatorBaseVisitor;
import antlr.caculator.gramma.caculatorParser;
import org.antlr.v4.runtime.tree.TerminalNode;

import java.math.BigDecimal;
import java.math.MathContext;

public class CaculatorVistorImpl extends caculatorBaseVisitor {
    @Override
    public Object visitPrintExpr(caculatorParser.PrintExprContext ctx) {
        System.out.println("进入visitPrintExpr");
        String id = ctx.Identifier().getText();
        String type = ctx.type().getText();
        caculatorParser.Multi_expContext  exprContext = ctx.multi_exp();
        Object result = visit(exprContext);
        String expr = ctx.multi_exp().getText();
        System.out.println("#result#"+result);
        return type+" "+id+"="+expr;
    }

    @Override
    public Object visitCalExpr(caculatorParser.CalExprContext ctx) {
        TerminalNode opmd = ctx.OPMD();
        caculatorParser.Multi_expContext left = ctx.multi_exp(0);
        caculatorParser.Multi_expContext right = ctx.multi_exp(1);
        Object l = visit(left);
        Object r = visit(right);
        if(l!=null&&r!=null){
            BigDecimal lv = new BigDecimal(l.toString());
            BigDecimal rv = new BigDecimal(r.toString());
            if(opmd.getText().equals(OperatorEnum.MUL.getSyntax())){
                BigDecimal multiply = lv.multiply(rv);
                multiply.setScale(CaculatorUtil.getRetainNum(l,r));
                return multiply.doubleValue();
            }else {
                BigDecimal div = lv.divide(rv);
                return div.doubleValue();
            }
        }
        return null;
    }

    @Override
    public Object visitNUM(caculatorParser.NUMContext ctx) {
        String text = ctx.NUM().getText();
        if(text.indexOf(".")>-1){
            return Double.parseDouble(text);
        }else {
            return Integer.parseInt(text);
        }
    }

    @Override
    public String visitId(caculatorParser.IdContext ctx) {
        return ctx.Identifier().getText();
    }

    @Override
    public Object visitPmExpr(caculatorParser.PmExprContext ctx) {
        TerminalNode opmd = ctx.OPPM();
        caculatorParser.Multi_expContext left = ctx.multi_exp(0);
        caculatorParser.Multi_expContext right = ctx.multi_exp(1);
        Object l = visit(left);
        Object r = visit(right);
        if(l!=null&&r!=null){
            int retainNum = CaculatorUtil.getRetainNum(left, right);
            BigDecimal lv = new BigDecimal(l.toString());
            BigDecimal rv = new BigDecimal(r.toString());
            if(opmd.getText().equals(OperatorEnum.PLUS.getSyntax())){
                BigDecimal plus = lv.add(rv);
                if(retainNum>0)
                    plus.setScale(retainNum);
                return retainNum>0?plus.doubleValue():plus.intValue();
            }else {
                BigDecimal minus = lv.subtract(new BigDecimal(rv.toString()));
                if(retainNum>0)
                    minus.setScale(retainNum);
                return retainNum>0?minus.doubleValue():minus.intValue();
            }
        }
        return null;
    }

    @Override
    public Object visitMulti(caculatorParser.MultiContext ctx) {
        return visit(ctx.multi_exp());
    }
}
